import * as HttpServer from 'http'
import * as express from 'express'
import * as bodyParser from 'body-parser'
import * as path from 'path'
import * as SocketIO from 'socket.io'
import { ClientRequest } from '../types/index';
import { globalEvent, Events } from '../global';

export default class WebServer {

  private http: HttpServer.Server
  private io: SocketIO.Server

  private webRoot: string = path.join(__dirname, '/web')

  private socketRequestMap: Map<string, SocketIO.Socket> = new Map<string, SocketIO.Socket>()

  constructor (port: number) {
    
    const app = express()
    app.use(bodyParser.json())
    app.use(bodyParser.urlencoded({ extended: false }))
    app.use(express.static(this.webRoot))
    
    this.http = HttpServer.createServer(app)
    this.io = SocketIO(this.http)

    this.io.on('connection', socket => {
      socket.on('request',(request: ClientRequest) => {
        this.socketRequestMap.set(request.id, socket)
        globalEvent.emit(Events.WebServer_Request, request)
      })
      socket.on('error', (err: Error) => {
        console.error(err)
      })
    })

    this.attachEvents()

    this.http.listen(port, () => {
      console.log('ui server start at port: ' + port)
    })
  }

  shutdown () {
    this.io.close()
    this.http.close()
    console.log('web server close')
  }

  private attachEvents (): void {
    globalEvent.on(Events.WebServer_Response, this.handleResponse)
    globalEvent.on(Events.WebServer_Push_QueueInfo, this.handlePushInfo)
  }

  private handleResponse (id, res): void {
    const socket = this.socketRequestMap.get(id)
    if (socket) {
      this.socketRequestMap.delete(id)
      socket.emit(`response_${id}`, res)
    }
  }

  private handlePushInfo (key: string, data: any):void {
    this.io.clients().emit(`push_${key}`, data)
  }
}